package com.yibo.zuul.config;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.yibo.redis.RedisCommand;
import com.yibo.support.context.SpringContext;
import com.yibo.support.helper.JsonHelper;
import com.yibo.support.jwt.JWTUtils;
import com.yibo.support.pojo.Result;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import static com.yibo.support.constant.ApiUrlConstant.PUBLIC_URL;
import static com.yibo.support.constant.YBConstant.*;

/**
 * 网关过滤
 *
 * @author zhanglei
 */
@Component
public class MyZuulFilter extends ZuulFilter {


    @Override
    public String filterType() {
        /**
         * Zuul有一下四种过滤器
         * "pre":是在请求路由到具体的服务之前执行,这种类型的过滤器可以做安全校验,例如身份校验,参数校验等
         * "routing":它用于将请求路由到具体的微服务实例,在默认情况下,它使用Http Client进行网络请求
         * "post":它是在请求已被路由到微服务后执行,一般情况下,用作收集统计信息,指标,以及将响应传输到客户端
         * "error":它是在其他过滤器发生错误时执行
         */
        return "pre";
    }

    @Override
    public int filterOrder() {
        //过滤顺序,值越小,越早执行该过滤器
        return 0;
    }

    @Override
    public boolean shouldFilter() {

        //表示该过滤器是否过滤逻辑,如果是ture,则执行run()方法;如果是false,则不执行run()方法.
        return true;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        //获取域名
        String ip = request.getRemoteHost();
        if (LOCAL_IP.equals(ip)) {
            ip = "127.0.0.1";
        }
        ctx.getZuulRequestHeaders().put(CLI_IP,ip);
        //如果是公有接口，直接放权
        String servletPath = request.getServletPath();
        if(servletPath.contains(PUBLIC_URL)){
            return null;
        }

        String token = request.getHeader("token");
        if(token == null || token.trim().equals("")){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            write(ctx,new Result(-120,"",null));
            return null;
        }
        //校验是否是rsa认证
        JWTUtils.JWTResult result = JWTUtils.getInstance().checkToken(token);
        if(!result.isStatus()){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            write(ctx,new Result(-120,result.getMsg(),null));
            return null;
        }
        RedisCommand command = SpringContext.getBean(RedisCommand.class);
        Object userValue = command.get(YIBO_USER_REDIS_PREFIX_TOKEN+token);
        if(userValue == null){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            write(ctx,new Result(-120,"",null));
            return null;
        }

        //将token设置到ctx
        ctx.getZuulRequestHeaders().put("token",token);
        return null;
    }


    private void write(RequestContext ctx,Result result){
        try{
            ctx.getResponse().getWriter().write(JsonHelper.toJson(result));
        }catch(Exception e){
            //此处拒绝抛出异常
        }
    }
}
